package com.chenxin.interact.process.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chenxin.common.core.domain.ProcResult;
import com.chenxin.common.enums.wms.IbMasterType;
import com.chenxin.common.enums.wms.ObMasterType;
import com.chenxin.common.utils.StringUtils;
import com.chenxin.common.utils.uuid.Seq;
import com.chenxin.interact.domain.mesToWms.MesToWmsIn;
import com.chenxin.interact.domain.mesToWms.MesToWmsOrder;
import com.chenxin.interact.domain.mesToWms.MesToWmsReturn;
import com.chenxin.interact.domain.mesRequest.MesInReqDTO;
import com.chenxin.interact.domain.mesRequest.MesOrderReqDTO;
import com.chenxin.interact.domain.mesRequest.MesReturnReqDTO;
import com.chenxin.interact.mapper.MesToWmsInMapper;
import com.chenxin.interact.mapper.MesToWmsOrderMapper;
import com.chenxin.interact.mapper.MesToWmsReturnMapper;
import com.chenxin.interact.process.IMesInteractProcess;
import com.chenxin.wms.domain.IbDetailEntity;
import com.chenxin.wms.domain.IbMasterEntity;
import com.chenxin.wms.domain.ObDetailEntity;
import com.chenxin.wms.domain.ObMasterEntity;
import com.chenxin.wms.mapper.IbDetailMapper;
import com.chenxin.wms.mapper.IbMasterMapper;
import com.chenxin.wms.mapper.ObDetailMapper;
import com.chenxin.wms.mapper.ObMasterMapper;
import com.chenxin.wms.process.stock.IStockProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MesInteractProcessImpl implements IMesInteractProcess {
    @Autowired
    private MesToWmsOrderMapper mesToWmsOrderMapper;
    @Autowired
    private MesToWmsReturnMapper mesToWmsReturnMapper;
    @Autowired
    private IbMasterMapper ibMasterMapper;
    @Autowired
    private IbDetailMapper ibDetailMapper;
    @Autowired
    private ObMasterMapper obMasterMapper;
    @Autowired
    private ObDetailMapper obDetailMapper;
    @Autowired
    private MesToWmsInMapper mesToWmsInMapper;
    @Autowired
    private IStockProcess stockProcess;

    @Override
    @Transactional
    public ProcResult procMesOrder(MesOrderReqDTO mesOrderReqDTO) {
        if (mesOrderReqDTO == null) {
            return ProcResult.error("order_err#001", "请求参数不能为空");
        }
        MesOrderReqDTO.Head head = mesOrderReqDTO.getHEAD();
        if (head == null) {
            return ProcResult.error("order_err#002", "请求头【HEAD】不能为空");
        }
        // 获取备料单号
        String stockNo = head.getStockNo();
        if (StringUtils.isBlank(stockNo)) {
            return ProcResult.error("order_err#003", "备料单号不能为空");
        }
        // 获取工单号
        String orderNo = head.getWorkOrderNo();
        // 车间编码
        String workShopCode = head.getWorkShopCode();
        // 产线编码
        String resourceCode = head.getResourceCode();
        // 叫料类型（5.首套料备料10.预警备料15转产备料20整工单备料30工单挪料35前加工备料40半成品流转45工单领料）
        String stockType = head.getStockType();
        // 创建人&创建时间
        String createBy = head.getCreateBy();
        String createDate = head.getCreateDate();
        Date workDate = new Date();
        if (StringUtils.isBlank(orderNo)) {
            return ProcResult.error("order_err#003", "工单号不能为空");
        }
        if (StringUtils.isBlank(workShopCode)) {
            return ProcResult.error("order_err#004", "车间编码不能为空");
        }
        if (StringUtils.isBlank(resourceCode)) {
            return ProcResult.error("order_err#005", "产线编码不能为空");
        }
        // 判断工单号是否重复下发
        QueryWrapper<MesToWmsOrder> stockNoQw = new QueryWrapper<>();
        stockNoQw.lambda().eq(MesToWmsOrder::getStockNo, stockNo).lt(MesToWmsOrder::getStatus, "4");
        Long rows = mesToWmsOrderMapper.selectCount(stockNoQw);
        if (rows > 0) {
            return ProcResult.error("order_err#004", "备料单【" + stockNo + "】重复叫料，请核查");
        }
        // DETAILS校验
        List<MesOrderReqDTO.DETAIL> details = mesOrderReqDTO.getDETAILS();
        if (details == null || details.size() == 0) {
            return ProcResult.error("order_err#005", "工单明细不能为空");
        }
        // 获取数据条数
        int detailSize = details.size();
        // 构建出库主单
        ObMasterEntity obMaster = new ObMasterEntity();
        String masterNo = Seq.getId();
        // 将HEAD信息写入出库主单中
        obMaster.setObMasterNo(masterNo);
        obMaster.setStockNo(stockNo);
        obMaster.setObMasterType(ObMasterType.CALL_WIP.getCode());
        obMaster.setFromErp("1");
        obMaster.setWorkOrderNo(orderNo);
        obMaster.setWorkShopCode(workShopCode);
        obMaster.setResourceCode(resourceCode);
        obMaster.setCreator(101L);
        obMaster.setCreateDate(workDate);
        obMasterMapper.insert(obMaster);

        // 构建order接口list
        List<MesToWmsOrder> orderList = new ArrayList<>();

        // 构建出库单明细list
        List<ObDetailEntity> obDetailList = new ArrayList<>();
        // 对数据进行处理（循环处理details）
        for (MesOrderReqDTO.DETAIL detail : details) {
            // 物料编号
            String spuNo = detail.getItemCode();
            // 需求数量
            BigDecimal reqQty = detail.getStanceDemandQty();
            // 单词数量
            BigDecimal singleQty = detail.getSingleQty();

            // 所需库存齐套性校验(TODO 临时注释)
            //ProcResult checkResult = stockProcess.procWmsStockCheck(spuNo, reqQty);
            //if (!WmsConstants.PROC_SUCCESS.equals(checkResult.getCode())) {
            //    return ProcResult.error("order_err#006", checkResult.getMessage());
            //}
            // 成功后将数据写入接口表
            MesToWmsOrder order = new MesToWmsOrder();
            ObDetailEntity obDetail = new ObDetailEntity();
            order.setStockNo(stockNo);
            order.setWorkOrderNo(orderNo);
            order.setWorkShopCode(workShopCode);
            order.setResourceCode(resourceCode);
            order.setStockType(stockType);
            order.setMesCreateBy(createBy);
            order.setMesCreateDate(createDate);
            order.setCreator(101L);
            order.setCreateDate(workDate);
            // 写入detail信息
            order.setLine(detail.getLine());
            order.setItemCode(spuNo);
            order.setStanceDemandQty(reqQty);
            order.setSingleQty(singleQty);
            order.setEquipAccountId(detail.getEquipAccountId());
            order.setSubarea(detail.getSubarea());
            order.setStance(detail.getStance());
            order.setStatus("0");
            order.setCreator(101L);
            order.setCreateDate(workDate);

            // 写入ob_detail信息
            obDetail.setObMasterId(obMaster.getObMasterId());
            obDetail.setObMasterNo(masterNo);
            obDetail.setSpuNo(spuNo);
            obDetail.setObPlanQty(reqQty);
            obDetail.setSingleQty(singleQty);
            obDetail.setEquipAccountId(detail.getEquipAccountId());
            obDetail.setSubarea(detail.getSubarea());
            obDetail.setStance(detail.getStance());
            obDetail.setCreator(101L);
            // 记录至list中（用于统一写入数据库）
            orderList.add(order);
            obDetailList.add(obDetail);
        }

        // 写入数据库
        mesToWmsOrderMapper.insert(orderList, detailSize);
        obDetailMapper.insert(obDetailList, detailSize);
        // 开始备货处理（按单备货）
        return ProcResult.success("备料单【" + stockNo + "】下发成功，数据【" + detailSize + "】条!");
    }

    @Override
    public ProcResult procMesReturn(MesReturnReqDTO mesReturnReqDTO) {
        if (mesReturnReqDTO == null) {
            return ProcResult.error("return_err#001", "请求参数不能为空");
        }
        MesReturnReqDTO.Head head = mesReturnReqDTO.getHEAD();
        if (head == null) {
            return ProcResult.error("return_err#002", "请求头【HEAD】不能为空");
        }
        // 获取主要数据（退料单号、退料类型、退料仓库、退料部门）
        String returnNo = head.getReturnNo();
        if (StringUtils.isBlank(returnNo)) {
            return ProcResult.error("return_err#003", "退料单号不能为空");
        }
        String orderType = head.getOrderType();
        if (StringUtils.isBlank(orderType)) {
            return ProcResult.error("return_err#004", "退料类型不能为空");
        }
        String sendWarehouse = head.getSendWarehouse();

        Date workDate = new Date();

        // 校验退料单号是否存在
        QueryWrapper<MesToWmsReturn> returnNoQW = new QueryWrapper<>();
        returnNoQW.lambda().eq(MesToWmsReturn::getReturnNo, returnNo)
                .lt(MesToWmsReturn::getStatus, 4).last("limit 1");
        Long count = mesToWmsReturnMapper.selectCount(returnNoQW);
        if (count > 0) {
            return ProcResult.error("return_err#005", "退料单【" + returnNo + "】重复下发，请核查");
        }

        List<MesReturnReqDTO.DETAIL> details = mesReturnReqDTO.getDETAILS();

        // 构建退料单信息
        IbMasterEntity ibMasterEntity = new IbMasterEntity();
        String masterNo = Seq.getId();
        ibMasterEntity.setIbMasterNo(masterNo);
        ibMasterEntity.setOrderNo(returnNo);
        ibMasterEntity.setIbMasterType(IbMasterType.RETURN.getCode());
        ibMasterEntity.setFromErp("1");
        ibMasterEntity.setCreator(101L);
        ibMasterEntity.setCreateDate(workDate);
        ibMasterMapper.insert(ibMasterEntity);

        // 构建接口明细
        List<MesToWmsReturn> returnList = new ArrayList<>();
        // 构建退料单明细
        List<IbDetailEntity> ibDetailList = new ArrayList<>();

        //插入接口表
        for (MesReturnReqDTO.DETAIL detail : details) {
            // 填充接口内容
            MesToWmsReturn mesReturn = new MesToWmsReturn();
            mesReturn.setReturnNo(returnNo);

            mesReturn.setSendWarehouse(sendWarehouse);
            mesReturn.setEnterpriseName(head.getEnterpriseName());
            mesReturn.setOrderType(orderType);

            mesReturn.setLine(detail.getLine());
            mesReturn.setItemCode(detail.getItemCode());
            mesReturn.setReelId(detail.getReelId());
            mesReturn.setQty(detail.getQty());
            mesReturn.setWorkOrderNo(detail.getWorkOrderNo());
            mesReturn.setCreator(101L);
            mesReturn.setCreateDate(workDate);
            returnList.add(mesReturn);

            // 填充退料单明细
            IbDetailEntity returnDetail = new IbDetailEntity();
            returnDetail.setIbMasterId(ibMasterEntity.getIbMasterId());
            returnDetail.setIbMasterNo(masterNo);
            returnDetail.setLine(detail.getLine());
            returnDetail.setSpuNo(detail.getItemCode());
            returnDetail.setIbPlanQty(detail.getQty());
            returnDetail.setReelId(detail.getReelId());
            returnDetail.setCreator(101L);
            returnDetail.setCreateDate(workDate);
            ibDetailList.add(returnDetail);
        }
        // 批量写入数据
        mesToWmsReturnMapper.insert(returnList);
        ibDetailMapper.insert(ibDetailList);
        return ProcResult.success("退料单【" + returnNo + "】下发成功，数据【" + details.size() + "】条");
    }

    @Override
    @Transactional
    public ProcResult procMesIn(MesInReqDTO mesInReqDTO) {
        Date workDate = new Date();

        MesInReqDTO.Head head = mesInReqDTO.getHEAD();
        List<MesInReqDTO.DETAIL> details = mesInReqDTO.getDETAILS();

        // 入库单号
        String inStorageNo = head.getInStorageNo();
        // 工单号
        String workOrderNo = head.getWorkOrderNo();
        // 物料类型
        String itemType = head.getItemType();

        // 判断入库单号是否存在
        QueryWrapper<MesToWmsIn> inStorageNoQW = new QueryWrapper<>();
        inStorageNoQW.lambda().eq(MesToWmsIn::getInStorageNo, inStorageNo)
                .lt(MesToWmsIn::getStatus, 4).last("limit 1");
        Long count = mesToWmsInMapper.selectCount(inStorageNoQW);
        if (count > 0) {
            return ProcResult.error("in_err#001", "入库单【" + inStorageNo + "】重复下发，请核查");
        }
        // 构建成品入库主单信息
        IbMasterEntity ibMaster = new IbMasterEntity();
        // 获取单据流水号
        String masterNo = Seq.getId();

        // 处理HEAD数据
        ibMaster.setIbMasterNo(masterNo);
        ibMaster.setOrderNo(inStorageNo);
        ibMaster.setFromErp("1");
        ibMaster.setIbMasterType(IbMasterType.IN_FG.getCode());
        ibMaster.setWorkOrderNo(workOrderNo);
        ibMaster.setCreator(101L);
        ibMaster.setCreateDate(workDate);
        ibMasterMapper.insert(ibMaster);

        // 构建接口明细List
        List<MesToWmsIn> inList = new ArrayList<>(details.size());
        // 构建入库单明细List
        List<IbDetailEntity> ibDetailList = new ArrayList<>(details.size());
        // 处理接口数据以及生成成品入库单据
        for (MesInReqDTO.DETAIL detail : details) {
            MesToWmsIn mesToWmsIn = new MesToWmsIn();
            IbDetailEntity ibDetail = new IbDetailEntity();
            mesToWmsIn.setInStorageNo(inStorageNo);
            mesToWmsIn.setWorkOrderNo(workOrderNo);
            mesToWmsIn.setErpStorageNo(head.getErpStorageNo());
            mesToWmsIn.setEnterpriseName(head.getEnterpriseName());
            // 行号
            mesToWmsIn.setLine(detail.getLine());
            mesToWmsIn.setItemCode(detail.getItemCode());
            mesToWmsIn.setItemType(itemType);
            mesToWmsIn.setQty(detail.getQty());
            mesToWmsIn.setLabelNo(detail.getLabelNo());
            mesToWmsIn.setBatchBarcode(detail.getBatchBarcode());
            mesToWmsIn.setBarCode(detail.getBarcode());
            mesToWmsIn.setStorageDate(detail.getStorageDate());
            mesToWmsIn.setCreator(101L);
            mesToWmsIn.setCreateDate(workDate);
            inList.add(mesToWmsIn);
            // 插入入库单明细
            ibDetail.setIbMasterId(ibMaster.getIbMasterId());
            ibDetail.setIbMasterNo(masterNo);
            ibDetail.setOrderNo(inStorageNo);
            ibDetail.setLine(detail.getLine());
            ibDetail.setSpuNo(detail.getItemCode());
            ibDetail.setIbPlanQty(detail.getQty());
            ibDetail.setLabelNo(detail.getLabelNo());
            ibDetail.setBatchBarcode(detail.getBatchBarcode());
            ibDetail.setBarcode(detail.getBarcode());
            ibDetail.setCreator(101L);
            ibDetail.setCreateDate(workDate);
            ibDetailList.add(ibDetail);
        }
        mesToWmsInMapper.insert(inList);
        ibDetailMapper.insert(ibDetailList);
        return ProcResult.success("入库单工单【" + inStorageNo + "】下发成功，数据【" + details.size() + "】条");
    }
}
